package com.springboot.cloud.order.service.impl;

import com.springboot.cloud.common.core.enums.OrderStatusEnum;
import com.springboot.cloud.common.web.entity.dto.GoodsDto;
import com.springboot.cloud.common.web.entity.vo.SecKillMessage;
import com.springboot.cloud.goods.feign.GoodsFeign;
import com.springboot.cloud.order.dao.OrderRepository;
import com.springboot.cloud.order.entity.Order;
import com.springboot.cloud.order.service.IOrderService;
import com.springboot.cloud.seckill.feign.SeckillFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;

/**
 * @author godyao
 * @date 2022/3/26
 */
@Service
@Slf4j
public class OrderServiceImpl implements IOrderService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SeckillFeign seckillFeign;

    @Autowired
    private GoodsFeign goodsFeign;

    @Autowired
    private OrderRepository orderRepository;

    /**
     * redis中秒杀key前缀
     */
    private static final String SEC_KILL_KEY_PREFIX = "SECKILLGOODS:";
    /**
     * redis中商品订单key前缀
     */
    private static final String SEC_KILL_GOODS_KEY_PREFIX = "SECKILLORDER:";
    /**
     * 如果跨数据节点需要采用分布式事务
     * @param secKillMessage
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Order makeOrder(SecKillMessage secKillMessage) {
        final Long userId = secKillMessage.getUserId();
        final Long goodsId = secKillMessage.getGoodsId();
        // 从redis获取库存 更新数据库 PS：这里不急要每次都更新数据库，可以选择一个时间点将redis的库存一次同步到mysql中
        final Integer stockCount = (Integer) redisTemplate.opsForValue().get(SEC_KILL_KEY_PREFIX + goodsId);
        log.info("redis中的库存数={}", stockCount);
        seckillFeign.updateStockByGoodsId(goodsId, stockCount);
        final GoodsDto goods = goodsFeign.find(goodsId).getData();
        // 创建订单
        final Order order = orderRepository.save(new Order().setUserId(userId).setGoodsId(goodsId).setGoodsName(goods.getGoodsName()).setGoodsCount(1).setGoodsPrice(goods.getGoodsPrice())
                .setCreateDate(Instant.now()).setStatus(OrderStatusEnum.PENDING_PAY.getCode()));
        // 下单后的记录在redis中， 供客户端轮训查询结果 减少数据库压力和用户超买判断（这里每个用户限购一件，如果可以购买多件的话需要维护一个下单次数）
        String key = "userId=" + userId + "goodsId=" + goodsId;
        redisTemplate.opsForValue().set(SEC_KILL_GOODS_KEY_PREFIX+key, OrderStatusEnum.PENDING_PAY.getCode());
        return order;
    }
}
